#pragma once

#include <algorithm>
#include <hash_map>
#include <vector>
#include "Parent.h"

using namespace stdext;
using namespace std;

//return true if i is presented in v
bool Parent::isPresent(vector<Type::Index::Line> v, Type::Index::Line i){
	vector<Type::Index::Line>::iterator iter;
	return (std::find(v.begin(), v.end(), i) != v.end());
}

Parent::Parent(void) {		
	Parent::parentBitMapSetFlag = false;
}
Parent::~Parent(void){
	Parent::parentBitMapSetFlag = false;
	Parent::parentRelation.clear();
	Parent::revertParentRelation.clear();
}

void Parent::setParent(Type::Index::Line p, Type::Index::Line c){
	if (parentRelation.find(p) != parentRelation.end()){
		parentRelation.find(p)->second.push_back(c);
	}else{
		vector<Type::Index::Line> listOfChild;
		listOfChild.push_back(c);
		parentRelation[p] = listOfChild;
	}
	if (revertParentRelation.find(c)==revertParentRelation.end()){
		revertParentRelation[c] = p;
	}else{
		Type::Index::Line temp = revertParentRelation[c];
		parentRelation.find(temp)->second.erase(std::remove(parentRelation.find(temp)->second.begin(), 
			                                                parentRelation.find(temp)->second.end(), c), 
			                                                parentRelation.find(temp)->second.end());
		revertParentRelation[c] = p;

	}
}
		
vector<Type::Index::Line> Parent::getChild(Type::Index::Line p){
	if (parentRelation.find(p) != parentRelation.end()) {
		return parentRelation.find(p)->second;
	} 
	return vector<Type::Index::Line>();
}
Type::Index::Line Parent::getParent(Type::Index::Line c){
	hash_map<Type::Index::Line,Type::Index::Line>::const_iterator hm_rcIter;
	hm_rcIter = revertParentRelation.find(c);
	if (hm_rcIter == revertParentRelation.end()){
		return -1;
	}else{
		return hm_rcIter->second;
	}
}

bool Parent::hasParent(Type::Index::Line c){
	if (getParent(c) == -1){
		return false;
	}else{
		return true;
	}
}
bool Parent::hasChild(Type::Index::Line p){
	if (parentRelation.find(p) == parentRelation.end()){
		return false;
	}else{
		return true;
	}
}	
bool Parent::isParent(Type::Index::Line p, Type::Index::Line c){
	if (Parent::parentBitMapSetFlag){
		return Parent::parentBitMap.at(p).at(c);	
	}else{
		return p == Parent::getParent(c);
	}
}
bool Parent::setParentBitMap(vector<vector<bool>> CBM){
	if (CBM.empty()){
		return Parent::parentBitMapSetFlag;
	}else{
		int parentsize = CBM.size();
		int childsize = CBM.at(0).size();
		parentBitMap.resize(parentsize, vector<bool>(childsize,false));
		for (int i=0; i<parentsize;i++){
			for (int j=0; j<childsize;j++){
				if (Parent::getParent(j) != i && CBM.at(i).at(j)){
					return Parent::parentBitMapSetFlag;
				}
				parentBitMap.at(i).at(j) = CBM.at(i).at(j);
			}
		}
		Parent::parentBitMapSetFlag = true;
		return Parent::parentBitMapSetFlag;
	}
}
bool Parent::isBitMapSet(){
	return Parent::parentBitMapSetFlag;
}